import React, { forwardRef, useContext, useMemo } from "react"
import useMergeProps from "@/hooks/useMergeProps"
import { ConfigContext } from "../config-provider"
import { cs, isNumber, isObject, isArray } from "@/utils"
import { RowContext } from "./context"
const defaultProps = {
    span: 24
}
const getFlexString = (flex) => {
    if (typeof flex === "string" && /\d+[(px|%|em|rem)]{1}/.test(flex)) {
        return `0 0 ${flex}`
    }
    return flex
}
/**
 *
 * @param {Object} props
 * @param {React.RefObject} ref
 * @param {number} [props.span] 栅格占位格数
 * @param {number} [props.offset] 栅格左侧的间隔格数，间隔内不可以有栅格
 * @param {number} [props.order] 对元素进行排序
 * @param {number} [props.pull] 对元素进行排序
 * @param {number} [props.push] 对元素进行排序
 * @param {string | number | "auto" | "none"} [props.flex] 设置 flex 布局属性
 * @param {	number | { [key: string]: any }} [props.lg] >= 992px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.md] >= 768px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.sm] >= 576px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.xl] >= 1200px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.xs] < 576px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.xxl] >= 1600px 响应式栅格
 * @param {	number | { [key: string]: any }} [props.xxxl] >= 2000px 响应式栅格 *
 * @param {React.CSSProperties} [props.style] 节点样式
 * @param {string | string[]} [props.className] 节点类名
 *
 * @returns {React.ReactNode}
 */
const ColComponent = (colProps, ref) => {
    const { getPrefixCls } = useContext(ConfigContext)
    const { gutter, div } = useContext(RowContext)
    const props = useMergeProps(colProps, defaultProps)
    const {
        children,
        className,
        style,
        span,
        order,
        offset,
        pull,
        push,
        flex,
        xs,
        sm,
        md,
        lg,
        xl,
        xxl,
        xxxl
    } = props
    const prefixCls = getPrefixCls("col")
    function adaptationGrid(prefixCls, mergeClassName) {
        const screeList = { xs, sm, md, lg, xl, xxl, xxl }
        Object.keys(screeList).forEach(screen => {
            const screenValue = screeList[screen]
            if (isNumber(screenValue)) {
                if (screenValue >= 0) {
                    mergeClassName[`${prefixCls}-${screen}-${screenValue}`] = true
                }
            } else if (isObject(screenValue)) {
                const { span, offset, order, push, pull } = screenValue
                mergeClassName[`${prefixCls}-${screen}-${span}`] = span
                mergeClassName[`${prefixCls}-${screen}-offset-${offset}`] = offset
                mergeClassName[`${prefixCls}-${screen}-order-${order}`] = order
                mergeClassName[`${prefixCls}-${screen}-pull-${pull}`] = pull
                mergeClassName[`${prefixCls}-${screen}-push-${push}`] = push
            }
        })
        return mergeClassName
    }
    let mergeClassName = {
        [`${prefixCls}`]: !div,
        [`${prefixCls}-order-${order}`]: order,
        [`${prefixCls}-${span}`]: !div && !xs && !sm && !md && !lg && !xl && !xxl && !xxxl,
        [`${prefixCls}-offset-${offset}`]: offset,
        [`${prefixCls}-pull-${pull}`]: pull,
        [`${prefixCls}-push-${push}`]: push,
    }
    mergeClassName = adaptationGrid(prefixCls, mergeClassName)
    const classNames = cs(flex ? prefixCls : mergeClassName, className)
    const getColStyle = useMemo(() => {
        const style = {}
        if (isArray(gutter) && !div) {
            const paddingHorizontal = (gutter[0] && gutter[0] / 2) || 0
            const paddingVertical = (gutter[1] && gutter[1] / 2) || 0
            if (paddingHorizontal) {
                style.paddingLeft = paddingHorizontal
                style.paddingRight = paddingHorizontal
            }
            if (paddingVertical) {
                style.paddingTop = paddingVertical
                style.paddingBottom = paddingVertical
            }
        }
        return style
    }, [gutter, div])
    const getFlexStyle = useMemo(() => (
        (getFlexString(flex) ? { flex: getFlexString(flex) } : {})
    ), [flex])
    return (
        <div
            ref={ref}
            style={{
                ...style,
                ...getColStyle,
                ...getFlexStyle,
            }}
            className={classNames}
        >
            {children}
        </div>
    )
}
const Col = forwardRef(ColComponent)
Col.displayName = "Col"
export default Col